package com.thienloc.omap.util;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class JsfUtil {

    public static Flash flashScope() {
        return (FacesContext.getCurrentInstance().getExternalContext().getFlash());
    }

    public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) {
        int size = selectOne ? entities.size() + 1 : entities.size();
        SelectItem[] items = new SelectItem[size];
        int i = 0;
        if (selectOne) {
            items[0] = new SelectItem("", "---");
            i++;
        }
        for (Object x : entities) {
            items[i++] = new SelectItem(x, x.toString());
        }
        return items;
    }

//    public static void addErrorMessage(Exception ex, String defaultMsg) {
//        String msg = ex.getLocalizedMessage();
//        if (msg != null && msg.length() > 0) {
//            addErrorMessage(msg);
//        } else {
//            addErrorMessage(defaultMsg);
//        }
//    }
    public static void addErrorMessage(String summaryKey, String detailKey, String bundle) {
        addMessage(FacesMessage.SEVERITY_ERROR, summaryKey, detailKey, bundle);
    }

    public static void addSuccessMessage(String summaryKey, String detailKey, String bundle) {
        addMessage(FacesMessage.SEVERITY_INFO, summaryKey, detailKey, bundle);
    }

    public static void addMessage(FacesMessage.Severity severity, String summaryKey, String detailKey, String bundle) {
        FacesMessage facesMsg = new FacesMessage(severity, getBundleMessage(bundle, summaryKey), getBundleMessage(bundle, detailKey));
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
    }

    public static void addErrorMessages(List<String> messageKeys, String bundle) {
        for (String messageKey : messageKeys) {
            addErrorMessage(messageKey, messageKey, bundle);
        }
    }

    public static void addErrorMessage(String summary, String detail) {
        addMessage(FacesMessage.SEVERITY_ERROR, summary, detail);
    }

    public static void addSuccessMessage(String summary, String detail) {
        addMessage(FacesMessage.SEVERITY_INFO, summary, detail);
    }

    public static void addMessage(FacesMessage.Severity severity, String summary, String detail) {
        FacesMessage facesMsg = new FacesMessage(severity, summary, detail);
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
    }

    public static void addErrorMessages(List<String> messages) {
        for (String messageKey : messages) {
            addErrorMessage(messageKey, messageKey);
        }
    }

    public static String getRequestParameter(String key) {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);
    }

    public static Map<String, String> getRequestParameterMap() {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
    }

    public static Object getObjectFromRequestParameter(String requestParameterName, Converter converter, UIComponent component) {
        String theId = JsfUtil.getRequestParameter(requestParameterName);
        return converter.getAsObject(FacesContext.getCurrentInstance(), component, theId);
    }

    public static void refreshPage(FacesContext context) {
        String viewId = context.getViewRoot().getViewId();
        ViewHandler handler = context.getApplication().getViewHandler();
        UIViewRoot root = handler.createView(context, viewId);
        root.setViewId(viewId);
        context.setViewRoot(root);
    }

    public static void redirectPage(FacesContext context, String url) {
        try {
            context.getExternalContext().redirect(url);
        } catch (IOException e) {
            throw new FacesException("Cannot redirect to " + url + " due to IO exception.", e);
        }
    }

    public static HttpServletRequest getRequest(FacesContext context) {
        return (HttpServletRequest) context.getExternalContext().getRequest();
    }

    public static String resolveActionURL(FacesContext context) {
        return context.getApplication().getViewHandler().getActionURL(context, context.getViewRoot().getViewId());
    }

    public static String[] getMultiValueRequestParameter(FacesContext context, String para) {
        return context.getExternalContext().getRequestParameterValuesMap().get(para);
    }

    public static String getRequestParameter(FacesContext context, String para) {
        return context.getExternalContext().getRequestParameterMap().get(para);
    }

    public static Object getBean(String expr) {
        FacesContext context = FacesContext.getCurrentInstance();
        Application app = context.getApplication();
        ValueExpression valueExpression = app.getExpressionFactory().createValueExpression(context.getELContext(), expr, Object.class);
//        ValueBinding binding = app.createValueBinding("#{" + expr + "}");
//        return binding.getValue(context);
        return valueExpression.getValue(context.getELContext());
    }

    public static String getRequestContextPath() {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
    }

    public static HttpSession getCurrentSession() {
        ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        HttpSession currentSession = (HttpSession) externalContext.getSession(true);
        return currentSession;
    }

    public static <T> T findBean(String beanName, Class<T> beanClass) {
        FacesContext context = FacesContext.getCurrentInstance();
        return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", beanClass));
    }

    public static String getBundleMessage(String bundle, String key) {
        FacesContext ctx = FacesContext.getCurrentInstance();
        ResourceBundle rb = ctx.getApplication().getResourceBundle(ctx, bundle);
        return rb.getString(key);
    }

    public static FacesMessage getBundleFacesMessage(String bundle, String summaryKey, String detailKey) {
        return new FacesMessage(getBundleMessage(bundle, summaryKey), getBundleMessage(bundle, detailKey));
    }

    public static Logger getLogger(Class<?> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("Class for logger is required.");
        }
        return LoggerFactory.getLogger(clazz.getName());
    }
}
